package top.ucat.boots.starter.oauth2.server.factory;

import lombok.extern.slf4j.Slf4j;
import top.ucat.boots.common.check.Assert;
import top.ucat.boots.common.exception.BaseException;
import top.ucat.boots.starter.oauth2.client.beans.oauth.OauthToken;
import top.ucat.boots.starter.oauth2.client.beans.oauth.SystemUser;
import top.ucat.boots.starter.oauth2.client.beans.oauth.UserCodeTypeEnum;
import top.ucat.boots.starter.oauth2.client.beans.oauth.login.QRLoginDto;
import top.ucat.boots.starter.oauth2.client.definition.UserCodeTypeDefinition;
import top.ucat.boots.starter.oauth2.client.entity.OauthClientDetails;
import top.ucat.boots.starter.oauth2.client.entity.OauthUserCredentials;
import top.ucat.boots.starter.oauth2.client.realm.AuthorizingRealm;
import top.ucat.boots.starter.oauth2.client.service.api.ClientService;
import top.ucat.boots.starter.oauth2.client.service.api.TokenService;
import top.ucat.boots.starter.oauth2.server.factory.base.LoginFactory;

/**
 * @Auther: Jun
 * @Date: 2019/9/3 18:05
 * @Description: 扫码单点登录工厂
 */

@Slf4j
public class ScanQRSsoFactory implements LoginFactory {

    private static ScanQRSsoFactory scanQRSsoFactory;

    private DefaultLoginFactory defaultLoginFactory;

    private AuthorizingRealm authorizingRealm;

    private TokenService tokenService;

    private ClientService clientService;

    public void setAuthorizingRealm(AuthorizingRealm authorizingRealm) {
        this.authorizingRealm = authorizingRealm;
    }

    public void setTokenService(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    public void setClientService(ClientService clientService) {
        this.clientService = clientService;
    }

    public static ScanQRSsoFactory getInstance() {
        return scanQRSsoFactory;
    }

    private ScanQRSsoFactory(DefaultLoginFactory defaultLoginFactory) {
        this.defaultLoginFactory = defaultLoginFactory;
    }

    public static ScanQRSsoFactory getInstance(DefaultLoginFactory defaultLoginFactory) {
        //单例扫码登录工厂
        if (scanQRSsoFactory == null) {
            synchronized (ScanQRSsoFactory.class) {
                if (scanQRSsoFactory == null) {
                    scanQRSsoFactory = new ScanQRSsoFactory(defaultLoginFactory);
                }
            }
        }
        return scanQRSsoFactory;
    }

    @Override
    public OauthUserCredentials getUserCredentials(String userCode, String userCodeType, String systemType) {
        return defaultLoginFactory.getUserCredentials(userCode, userCodeType, systemType);
    }

    @Override
    public OauthUserCredentials registerUserCredentials(String userId, String userCode, String userCodeType, String systemType) {
        return defaultLoginFactory.registerUserCredentials(userId, userCode, userCodeType, systemType);
    }

    @Override
    public OauthUserCredentials registerUserCredentials(String userId, String userCode, String userCodeType, String systemType, boolean isCheck) {
        return defaultLoginFactory.registerUserCredentials(userId, userCode, userCodeType, systemType, isCheck);
    }

    @Override
    public Object registerUser(String userId, String userCode, String userCodeType, String systemType) {
        OauthUserCredentials userCredentials = this.getUserCredentials(userCode, userCodeType, systemType);
        if (userCredentials != null) {
            //用户凭证不存在,创建用户,然后创建用户凭证
        } else {
            //用户存在
        }
        throw new BaseException("创建用户登录凭证失败", 400);
    }

    public OauthToken login(QRLoginDto dto) {
        Assert.isNotNull(this.clientService, "clientService missing", 400);
        OauthClientDetails client = this.clientService.getClient(dto.getClientId(), dto.getClientSecret());
        //用户标记
        String userSign = dto.getUserSign();
        log.debug("用户标识:[{}]", userSign);
        Assert.isNotEmpty(userSign, "用户标识不能为空", 400);
        OauthUserCredentials userCredential = this.getUserCredentials(userSign, UserCodeTypeDefinition.QR, dto.getSystemType());
        Assert.isNotNull(userCredential, "找不到用户凭证", 400);
        Assert.isNotNull(authorizingRealm, "authorizingRealm missing", 500);
        SystemUser systemUser = authorizingRealm.getQRUser(userCredential);
        Assert.isNotNull(systemUser, "用户不存在", 400);
        systemUser.setUserId(userCredential.getUserId());
        systemUser.setUserCode(userSign);
        systemUser.setSystemType(dto.getSystemType());
        systemUser.setUserCodeType(UserCodeTypeDefinition.QR);
        //密码正确，生成token
        Assert.isNotNull(tokenService, "tokenService missing", 400);
        OauthToken accessToken = tokenService.createLoginAccessToken(client, systemUser, dto.isRetainToken());
        return accessToken;
    }
}
